package cn.flkj.evidence.controllers;


import cn.flkj.evidence.EvidenceImpl;
import cn.flkj.evidence.modles.Evidence;
import cn.flkj.evidence.modles.User;
import cn.flkj.evidence.repositories.EvidenceMapper;
import cn.flkj.evidence.repositories.UserMapper;
import cn.flkj.evidence.sample.EvidenceData;
import cn.flkj.evidence.util.FileUtil;
import cn.flkj.evidence.util.MD5Util;
import cn.flkj.evidence.util.Result;
import cn.flkj.evidence.util.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.SignatureException;

/**
 * 1. 用户注册
 * 2. 用户jks存储
 * 3. 用户登录
 * 4. 用户上传存证原件
 * 5. 用户签证上链并签名
 * 6. 用户签证文件下载
 * 7. 用户溯源查询
 */
@Slf4j
@RestController
@CrossOrigin
@RequestMapping(value = "/user")
public class UserController {
    @Value("${upload.filePath}")
    private String uploadFilePath;
    private static final String USER = "user.jks";
    private static final String ARBITRATOR = "arbitrator.jks";
    private static final String DEPOSITOR = "depositor.jks";
    private static final String UNIVERSAL_PASSWORD = "123456"; //通用密码，防止写错
    private static final String EVIDENCE_SIGNERS_ADDRESS = "0x0f74e2529e561b2749034a3d235da8cf04ab8bea";  // 工厂合约地址
    /**
     * 使用Resources Idea 不会提示错误
     */
    @Resource
    private UserMapper userMapper;
    @Resource
    private EvidenceMapper evidenceMapper;

    private final EvidenceImpl evidenceImpl;

    public UserController(EvidenceImpl evidenceImpl) {
        this.evidenceImpl = evidenceImpl;
    }

    @GetMapping("/hello")
    public Result hello() {

        log.info("upload file path : " + uploadFilePath);
        return ResultUtil.success();
    }

    @PostMapping("/registerUser")
    public Result<String> registerUser() {
        // MySQL插入数据
        return ResultUtil.success();
    }

    @PostMapping("/applyJks")
    public Result applyJks() {
        // 存储文件到指定路径，一个用户一个目录
        // 一下简称账户目录
        // 根据身份证号创建JKS文件，并代为保存
        // 存储在key文件夹下，配合MySQL使用
        return ResultUtil.success();
    }

    @PostMapping("/login")
    public Result<String> login() {
        // 查询MySQL验证用户信息
        return ResultUtil.success();
    }


    @PostMapping("/upload")
    public Result<String> upload(@RequestParam("file") MultipartFile uploadFile,
                                 @RequestParam("userName") String userName) {

        if (uploadFile.isEmpty()) {
            return ResultUtil.error("50001", "文件为空");
        }
        log.info("User Name : " + userName);
        String fileName = uploadFile.getOriginalFilename();
        File dest = new File(this.uploadFilePath + fileName);
        String md5HashCode32;
        /*
            1. 保存文件到指定目录
            2. 计算文件hash
            3. 修改文件名字
         */
        try {
            uploadFile.transferTo(dest);
        } catch (IOException | IllegalStateException e) {
            log.error("文件保存到服务器出错！" + e);
            return ResultUtil.error("50002", "内部文件处理错误");
        }
        try {
            md5HashCode32 = FileUtil.md5HashCode32(this.uploadFilePath + fileName);
            FileUtil.rename(dest, md5HashCode32);
        } catch (FileNotFoundException e) {
            log.error("get  hash  error！" + e);
            return ResultUtil.error("50002", "内部文件处理错误");
        }
        String filePathUserEvidenceData = this.uploadFilePath + userName + "/evidence" + "/." + userName;
        FileUtil.createDir(filePathUserEvidenceData);
        File hashFile = new File(this.uploadFilePath + md5HashCode32);
        if (hashFile.renameTo(new File(this.uploadFilePath
                + userName + "/evidence/" + md5HashCode32))) {
            log.info(this.uploadFilePath + userName + "/evidence/" + md5HashCode32);
        }
        int max_id = evidenceMapper.evidenceIdMax();
        int user_id = userMapper.findByName(userName).getUser_id();


        //------------------------------------------------------------------------

        String newEvidenceAddress;
        try {
            newEvidenceAddress = evidenceImpl.newEvidence(
                    USER,
                    UNIVERSAL_PASSWORD,
                    UNIVERSAL_PASSWORD,
                    EVIDENCE_SIGNERS_ADDRESS,
                    String.valueOf(max_id + 1),
                    md5HashCode32).getValue();
        } catch (Exception e) {
            log.error("存证上联错误： " + e);
            return ResultUtil.error("50003", "上链错误");
        }

        evidenceMapper.insert(
                md5HashCode32,
                userName,
                fileName,
                newEvidenceAddress,
                user_id
        );
        return ResultUtil.success(newEvidenceAddress);
        // 并关联到用户帐号下
        // 在表详情列加入存证的详细
        // 存证保存到账户目录中
    }

//    @PostMapping("/sendSignatureToBlockChain")
//    public Result<Object> sendSignatureToBlockChain() {
//        // 获取用户 keyStorePassword, keyPassword, 并且验证数据库
//        // 读取用户目录JKS文件
//        // 签名并上链
//        // 存证机构验证上链是否成功，并签名
//        // 发送打包消息到仲裁机构
//        return ResultUtil.success();
//    }


    @PostMapping("/userVerifyEvidence")
    public Result<Boolean> userVerifyEvidence(@RequestParam("transactionHash") String transactionHash) {
        EvidenceData evidenceData1;
        try {
            evidenceData1 = evidenceImpl.getEvidence(
                    USER, UNIVERSAL_PASSWORD, UNIVERSAL_PASSWORD,
                    transactionHash);
        } catch (Exception e) {
            return ResultUtil.error("5004", "链上获取存证失败！");
        }
        boolean flag;
        try {
            flag = evidenceImpl.verifyEvidence(evidenceData1);
            if (flag) {
               log.info("--------verifyEvidence success:" + flag);
            } else {
                log.info("--------verifyEvidence failed:" + flag);
            }
        } catch (SignatureException e) {
            return ResultUtil.error("5005", "链上溯源存证失败！");
        }

        return ResultUtil.success(flag);
    }

    @PostMapping("/findByName")
    public Result<User> userFindByName(@RequestParam("user") String userName) {
        User user = userMapper.findByName(userName);
        return ResultUtil.success(user);
    }

    @PostMapping("/evidenceInsert")
    public Result<Integer> evidenceInsert(
            @RequestParam("evidence_md5") String evidence_md5,
            @RequestParam("user") String user,
            @RequestParam("evidence_name") String evidence_name,
            @RequestParam("evidence_address") String evidence_address,
            @RequestParam("user_id") int user_id
    ) {
        int once = evidenceMapper.insert(evidence_md5, user, evidence_name, evidence_address, user_id);
        return ResultUtil.success(once);
    }

    @PostMapping("/evidenceSelectByEvidenceMd5")
    public Result<Evidence> evidenceSelect(@RequestParam("evidenceMd5") String evidence_md5) {
        Evidence once = evidenceMapper.findByEvidenceMd5(evidence_md5);
        if (once == null) {
            log.warn("once is null ");
        }
        return ResultUtil.success(once);
    }

    @GetMapping("/evidenceMax")
    public Result<Integer> evidenceMax() {
        Integer once = evidenceMapper.evidenceIdMax();
        return ResultUtil.success(once);
    }

    @PostMapping("/getEvidenceAddressByFileName")
    public Result<String> getEvidenceAddressByFileName(@RequestParam("fileName") String filName) {

        return ResultUtil.success("");
    }


}
